package top.mcwebsite.lib.router.processor.utils

import com.google.devtools.ksp.symbol.KSType
import com.squareup.kotlinpoet.BOOLEAN
import com.squareup.kotlinpoet.BOOLEAN_ARRAY
import com.squareup.kotlinpoet.BYTE
import com.squareup.kotlinpoet.BYTE_ARRAY
import com.squareup.kotlinpoet.CHAR
import com.squareup.kotlinpoet.CHAR_ARRAY
import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.DOUBLE
import com.squareup.kotlinpoet.DOUBLE_ARRAY
import com.squareup.kotlinpoet.FLOAT
import com.squareup.kotlinpoet.FLOAT_ARRAY
import com.squareup.kotlinpoet.INT
import com.squareup.kotlinpoet.INT_ARRAY
import com.squareup.kotlinpoet.LONG
import com.squareup.kotlinpoet.LONG_ARRAY
import com.squareup.kotlinpoet.SHORT
import com.squareup.kotlinpoet.SHORT_ARRAY
import com.squareup.kotlinpoet.STRING
import com.squareup.kotlinpoet.ksp.KotlinPoetKspPreview
import com.squareup.kotlinpoet.ksp.toClassName
import top.mcwebsite.lib.router.annotation.ParamType

lateinit var serializableType: KSType
lateinit var parcelableType: KSType

/**
 * TODO
 * 1. Type alias
 * 2. 如 List 这种类型的处理
 */
@OptIn(KotlinPoetKspPreview::class)
fun parseKsType(ksType: KSType): ParamType {
    return if (ksType.isParcelableType()) {
        // 需要判断是否是 TypeVariable
        ParamType.PARCELABLE
    } else if (ksType.isSerializable()) {
        ksType.toClassName().toParamType() ?: ParamType.SERIALIZATION
    } else {
        throw IllegalArgumentException("not support for $ksType")
    }
}

fun KSType.isSerializable(): Boolean {
    return serializableType.isAssignableFrom(this.makeNotNullable())
}

fun KSType.isParcelableType(): Boolean {
    return parcelableType.isAssignableFrom(this.makeNotNullable())
}

private fun ClassName.toParamType(): ParamType? =
    when (this) {
        BYTE -> ParamType.BYTE
        BYTE_ARRAY -> ParamType.BYTE_ARRAY
        SHORT -> ParamType.SHORT
        SHORT_ARRAY -> ParamType.SHORT_ARRAY
        INT -> ParamType.INT
        INT_ARRAY -> ParamType.INT_ARRAY
        LONG -> ParamType.LONG
        LONG_ARRAY -> ParamType.LONG_ARRAY
        FLOAT -> ParamType.FLOAT
        FLOAT_ARRAY -> ParamType.FLOAT_ARRAY
        DOUBLE -> ParamType.DOUBLE
        DOUBLE_ARRAY -> ParamType.DOUBLE_ARRAY
        CHAR -> ParamType.CHAR
        CHAR_ARRAY -> ParamType.CHAR_ARRAY
        BOOLEAN -> ParamType.BOOLEAN
        BOOLEAN_ARRAY -> ParamType.BOOLEAN_ARRAY
        STRING -> ParamType.STRING
        else -> null
    }
